package logx

import (
	"context"
	"fmt"
	"time"

	"github.com/todo/toolx/utilx/otlex"
	"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
	"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
	"go.opentelemetry.io/otel/exporters/stdout/stdoutlog"
	"go.opentelemetry.io/otel/sdk/log"
	"google.golang.org/grpc/credentials"
)

type Config otlex.ExporterConfig
type ConfigHandle = func(config *Config)

func (config Config) NewExporter(ctx context.Context, handles ...ConfigHandle) (log.Exporter, error) {
	for _, handle := range handles {
		handle(&config)
	}

	switch config.Type {
	case otlex.Grpc:
		options := make([]otlploggrpc.Option, 0, 1<<3)
		options = append(options,
			otlploggrpc.WithEndpoint(config.Endpoint),
			otlploggrpc.WithHeaders(config.Headers),
			otlploggrpc.WithTimeout(time.Second*time.Duration(config.Timeout)),
			otlploggrpc.WithRetry(otlploggrpc.RetryConfig{
				Enabled:         config.Retry.Enabled,
				InitialInterval: config.Retry.InitialInterval,
				MaxInterval:     config.Retry.MaxInterval,
				MaxElapsedTime:  config.Retry.MaxElapsedTime,
			}),
			otlploggrpc.WithReconnectionPeriod(time.Second*time.Duration(config.ReconnectionPeriod)),
			otlploggrpc.WithServiceConfig(config.ServiceConfig),
		)

		if config.Compression {
			options = append(options, otlploggrpc.WithCompressor("gzip"))
		}

		if config.Insecure {
			options = append(options, otlploggrpc.WithInsecure())
		}

		if !config.Insecure && config.TLS.IsEnable() {
			options = append(options, otlploggrpc.WithTLSCredentials(credentials.NewTLS(config.TLS.Tls())))
		}

		exporter, err := otlploggrpc.New(ctx, options...)
		if err != nil {
			return nil, err
		}

		return exporter, nil
	case otlex.Http:
		options := make([]otlploghttp.Option, 0, 1<<3)
		options = append(options, otlploghttp.WithEndpointURL(config.Endpoint),
			otlploghttp.WithHeaders(config.Headers),
			otlploghttp.WithTimeout(time.Second*time.Duration(config.Timeout)),
			otlploghttp.WithRetry(otlploghttp.RetryConfig{
				Enabled:         config.Retry.Enabled,
				InitialInterval: config.Retry.InitialInterval,
				MaxInterval:     config.Retry.MaxInterval,
				MaxElapsedTime:  config.Retry.MaxElapsedTime,
			}),
		)

		if config.Compression {
			options = append(options, otlploghttp.WithCompression(1))
		}

		if config.Insecure {
			options = append(options, otlploghttp.WithInsecure())
		}

		if !config.Insecure && config.TLS.IsEnable() {
			options = append(options, otlploghttp.WithTLSClientConfig(config.TLS.Tls()))
		}

		if len(config.URLPath) > 0 {
			options = append(options, otlploghttp.WithURLPath(config.URLPath))
		}

		exporter, err := otlploghttp.New(ctx, options...)
		if err != nil {
			return nil, err
		}

		return exporter, nil
	case otlex.Stdout:
		return stdoutlog.New()
	default:
		panic(fmt.Sprintf("NOT SUPPORT TRACE TYPE:%s", config.Type))
	}
}
